package com.wasp.collector.service;

import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.UnknownHostException;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.SSLException;

import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpRequest;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.protocol.HttpContext;

public class DefaultRetryHandler implements IRetryHandler{
	int sleepTime = 0;
	int maxRetryTimes = 3;
	public DefaultRetryHandler(int sleepTime,int maxRetryTimes){
		this.maxRetryTimes = maxRetryTimes;
		this.sleepTime = sleepTime;
	}
	public HttpRequestRetryHandler build(){
		HttpRequestRetryHandler myRetryHandler = new HttpRequestRetryHandler() {
			public boolean retryRequest(
					IOException exception,
					int executionCount,
					HttpContext context) {
				if (executionCount >= maxRetryTimes) {
					return false;
				}
				if(!handlerError(exception)){
					return false;
				}
				//如果设置，则sleep
				if(sleepTime>0){
					try {
						TimeUnit.MILLISECONDS.sleep(sleepTime);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				HttpClientContext clientContext = HttpClientContext.adapt(context);
				HttpRequest request = clientContext.getRequest();
				boolean idempotent = !(request instanceof HttpEntityEnclosingRequest);
				if (idempotent) {
					// Retry if the request is considered idempotent
					return true;
				}
				return false;
			}
			
		};
		return myRetryHandler;
	}
	
	private boolean handlerError(IOException exception){
		if (exception instanceof InterruptedIOException) {
			// Timeout
			return false;
		}
		if (exception instanceof UnknownHostException) {
			// Unknown host
			return false;
		}
		if (exception instanceof ConnectTimeoutException) {
			// Connection refused
			return false;
		}
		if (exception instanceof SSLException) {
			// SSL handshake exception
			return false;
		}
		return true;
	}
}